package com.bjc.netty.chat.protocol;

import com.bjc.netty.chat.config.Config;
import com.bjc.netty.chat.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;

/**
 * @program: nettypro
 * @description: 可以使用@sharablede Message
 *    必须和 LengthFieldBasedFrameDecoder一起使用，确保街道的ByteBuf消息使完整的
 * @author: bjc
 * @create: 2021-09-25 22:11
 */
@ChannelHandler.Sharable  //使之称为可以分享的handler
@Slf4j
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf, Message> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {
        ByteBuf out = ctx.alloc().buffer();
        //1. 4字节的魔数
        out.writeBytes(new byte[]{1, 2, 3, 4});
        //2. 1字节的版本号
        out.writeByte(1);
        //3. 1字节的序列化方式jdk 0 ，json 1
        out.writeByte(Config.getSerializerAlgorithm().ordinal());
        //4. 1字节的指令类型
        out.writeByte(msg.getMessageType());
        //5. 4字节的序列号
        out.writeInt(msg.getMessageType());
        //无意义，只为了对齐填充
        out.writeByte(0xff);
        //6. 获取内容的字节数组
//        ByteArrayOutputStream bos = new ByteArrayOutputStream();
//        ObjectOutputStream oos = new ObjectOutputStream(bos);
//        oos.writeObject(msg);
//        byte[] bytes = bos.toByteArray();
        //优化
        byte[] bytes = Config.getSerializerAlgorithm().serialize(msg);
        //7.正文长度
        out.writeInt(bytes.length);
        //8.写入内容
        out.writeBytes(bytes);
        outList.add(out);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int magicNum = in.readInt();
        byte version = in.readByte();
        byte serializerAlgorithm = in.readByte();  //0 或1
        byte messageType = in.readByte();
        int sequenceId = in.readInt();
        in.readByte();
        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readBytes(bytes,0,length);
//        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
//        Message message = (Message) ois.readObject();
        //优化 找到反序列化算法
        Serializer.Algorithm algorithm = Serializer.Algorithm.values()[serializerAlgorithm];
        //确定具体消息类型
        Class<? extends Message> messageClass = Message.getMessageClass(messageType);
        Message message = algorithm.deserialize(messageClass, bytes);

        log.debug("{},{},{},{},{},{}",magicNum,version,serializerAlgorithm,messageType,sequenceId,length);
        log.debug("{}",message);
        out.add(message);
    }
}
